Une des applications les plus complètes à développer: - entrées-sorties (charger configuration, envoyer fichier) - informations sur les fichiers (taille, mime, date de modification) - lister contenu d'un dossier - fork (pour lancer un CGI) - obtenir heure courante du système - sockets, en mode avancé: socket multiclients - conformation à un protocole - traitement de chaîne de caractères (parser la requête) Ici minimaliste, pour ne pas dire en chantier. /* Programme : Serveur HTTP Compilation : c httpBX httpBX.c -L../../lib -lservLib Auteur : Masta Date : 2006 */ #include "../../include/servLib.h" #include <sys/sendfile.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> /*============================================================================== Point d' entrée. ==============================================================================*/ int main() { // Parse la configuration // www folder ? // lister les dossiers, ou 403? // index par défaut? index.htm, index.html, index.php... // activer server signature ? //Lance le serveur sur le port TCP 80, pour 32 clients maximum. cbx_Serveur_Start(8080, 32); return 0; } /*============================================================================== Nouveau client a été accepté ==============================================================================*/ void onAccept(int idRequest, SOCKET i) { //printf ("Socket %d accepté\n", i); } /*============================================================================== Des données arrivent. Renvoie la chaîne au client. ==============================================================================*/ void onData_Arrival(SOCKET i, char *request, short nbytes) { int pF, n; struct stat buf; char header[255]; time_t rawtime; char mot[255]; unsigned char b=0, cpt=0; unsigned short lenURI=0; char *defindex="index.htm"; //typedef struct { char *method =NULL; char *URI =NULL; char *protoversion =NULL; //} requete; puts(request); //cbx_log (request); // retrouve l' IP //inet_ntoa(CliAddr.sin_addr) <- le passer en char depuis servLib // parse requête /* GET / HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 Firefox/1.5.0.8 Accept: text/xml;q=0.5 Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive */ // parse la 1re ligne de la requête while (*request!=0) { if (request[0]==' ' || request[0]==0XA) { mot[b]=0; b=0; if (cpt==0) method=strdup(mot); else if (cpt==1) {URI=strdup(mot); lenURI=b; } else if (cpt==2) {protoversion =strdup(mot); break;} cpt++; } else mot[b++]=request[0]; request++; } if (lenURI>255) { cbx_log ("%s|%s|414\n", method, URI); if (send(i, "HTTP/1.1 414\r\n\r\n<H2>Request-URL too long</H2>", 45, 0) == -1) perror("send()"); } else if (method[0]=='G' && method[1]=='E' && method[2]=='T') { //puts("ok, get"); if (URI[lenURI]=='/') // c'est un dossier URI = strdup(defindex); pF = open(URI, O_RDONLY); // si ressource n' existe pas: 404 if (!pF) { cbx_log ("%s|%s|404\n", method, URI); if (send(i, "HTTP/1.1 404\r\n\r\n<H2>Not found</H2>", 34, 0) == -1) perror("send()"); } else { if ( fstat(pF, &buf)==-1) perror("fstat()"); else { cbx_log ("%s|%s|200|%d\n", method, URI, buf.st_size); time ( &rawtime ); n = sprintf( header, "HTTP/1.1 200 OK\n" "Date:%s" "Server:httpBX/1.1 (GNU/Linux)\n" "Last-Modified:%s" "Accept-Ranges:bytes\n" "Content-Length:%ld\n" "Content-Type:text/html; charset=iso-8859-1\r\n\r\n", ctime (&rawtime), ctime (&buf.st_ctime), buf.st_size); // envoie le header if (send(i, header, n, 0) == -1) perror("send()"); // si CGI: pipe sur interpréteur // ouvre ressource en binaire et envoie. sendfile du kernel? if (sendfile(i, pF, 0, n) == -1) perror("sendfile"); } close(pF); } } else { cbx_log ("%s|%s|405\n", method, URI); n = sprintf( header, "HTTP/1.1 405\n" "Server:httpBX/1.0 (GNU/Linux)\n" "Content-Length:53\n" "Content-Type:text/html; charset=iso-8859-1\r\n\r\n" "<H1>405 Method not allowed</H1>Only GET is supported."); if (send(i, header, n, 0) == -1) perror("send()"); } // ferme connection closesocket(i); cbx_Serveur_Stop(); } /*============================================================================== Un client quitte. ==============================================================================*/ void onClient_Left(SOCKET i) { printf("Le socket %d vient de fermer sa connection\n", i); } /*============================================================================== Survient en cas d' erreur inopinée ==============================================================================*/ void onError (SOCKET i, char *errmsg) { fprintf(stderr, "Erreur sur le socket %d: %s\n", i, errmsg); }